from typing import Optional, TypeVar

from zkl_registries import TagKey

VT = TypeVar('VT', bound=type)
QT = TypeVar('QT', bound=type)


class SubTypeTagKey(TagKey[VT, QT, Optional[bool]]):
    """ Matches if the value is a subclass of the query """

    def __init__(self, name: str):
        self._name = name

    @property
    def name(self) -> str:
        return self._name

    def match(self, query: Optional[QT], val: Optional[VT]) -> Optional[bool]:
        if query is None:
            return True
        if val is None:
            return None
        return issubclass(val, query)


class SupTypeTagKey(TagKey[VT, QT, int]):
    """ Matches if the value is a superclass of the query """

    def __init__(self, name: str):
        self._name = name

    @property
    def name(self) -> str:
        return self._name

    def match(self, query: Optional[QT], val: Optional[VT]) -> Optional[int]:
        if query is None:
            return 0  # weak match
        if val is None:
            return None
        try:
            mro = type.mro(query)
            return len(mro) - 1 - mro.index(val)
        except ValueError:
            return None
